/*
 * @Description:动作
 * @Author: maskMan
 * @LastEditTime: 2024-04-04 16:47:01
 */

import { Color, Component, macro, Node, Prefab, Sprite, Tween, tween, TweenEasing, UIOpacity, v3, Vec3, __private } from 'cc'
import { ActionRet } from '../define/constants'
import QuickManager from './quickManager'
export default class Action extends Component {
  static instance: Action
  /**游戏更新帧率 */
  deltaTime: number
  /**
   *
   * @description: 放大缩小动作后销毁
   * @param {Node} targetNode  目标节点
   * @param {Node} time  时间
   * @return {*}
   */
  static scaleToDestroy(targetNode: Node, time: number = 0.3): ActionRet<Node> {
    return new Promise((resolve) => {
      const startScale = v3().multiplyScalar(0.3)
      const endScale = targetNode.getScale().add(startScale).multiplyScalar(-1)
      const tw = tween(targetNode)
        .by(time - 0.2, { scale: startScale }, { easing: 'backOut' })
        .by(time, { scale: endScale }, { easing: 'backIn' })
        .destroySelf()
        .call(() => {
          return resolve({ tw })
        })
      tw.start()
    })
  }
  /**
   * @description: 相对缩放动作
   * @param {Vec3} tarScale 缩放值
   * @param {number} time 时间
   * @param {string} easing 缓动名字
   * @return {*}
   */
  static scaleToAction(tarScale: Vec3 = v3(1, 1, 1), time: number = 1, easing?: TweenEasing): Tween<Node> {
    return tween().to(time, { scale: tarScale }, { easing })
  }
  /**
   * @description: 绝对缩放动作
   * @param {Vec3} offset 缩放偏移值
   * @param {number} time 时间
   * @return {*}
   */
  static scaleByAction(offset: Vec3 = v3(1, 1, 1), time: number = 1, easing?: TweenEasing): Tween<Node> {
    return tween().by(time, { scale: offset }, { easing })
  }
  /**
   * @description: 绝对旋转动作
   * @param {Vec3} tarAngle 旋转度数
   * @param {number} time 时间
   * @return {*}
   */
  static rotateToAction(tarAngle: Vec3 = v3(0, 0, 1), time: number = 1, easing?: TweenEasing): Tween<Node> {
    return tween().to(time, { angle: tarAngle }, { easing })
  }
  /**
   * @description: 相对旋转动作
   * @param {Vec3} offset 绝对旋转度数
   * @param {number} time 时间
   * @return {*}
   */
  static rotateByAction(offset: Vec3 = v3(1, 1, 1), time: number = 1, easing?: TweenEasing): Tween<Node> {
    return tween().by(time, { angle: offset }, { easing })
  }
  /**
   * @description: 绝对移动动作
   * @param {Vec3} tarPos 目标点
   * @param {number} time 时间
   * @return {*}
   */
  static moveToAction(tarPos: Vec3, time: number = 1, easing?: TweenEasing): Tween<Node> {
    return tween().to(time, { position: tarPos }, { easing })
  }
  /**
   * @description: 相对移动动作
   * @param {Vec3} offset 偏移目标点
   * @param {number} time 时间
   * @return {*}
   */
  static moveByAction(offset: Vec3, time: number = 1, easing?: TweenEasing): Tween<Node> {
    return tween().by(time, { position: offset }, { easing })
  }
  /**
   * @description: 颜色变化动作
   * @param {Color} color 颜色值
   * @param {number} time 时间
   * @return {*}
   */
  static colorToAction(color: Color, time: number = 1): Tween<Sprite> {
    return tween().to(time, { color: color })
  }
  /**
   * @description: 透明度淡入动作
   * @param {number} time 时间
   * @return {*}
   */
  static fadeInAction(time: number = 1): Tween<UIOpacity> {
    return tween().to(time, { opacity: 255 })
  }
  /**
   * @description: 透明度淡出动作
   * @param {number} time 时间
   * @return {*}
   */
  static fadeOutAction(time: number = 1): Tween<UIOpacity> {
    return tween().to(time, { opacity: 0 })
  }
  /**
   * @description: 闪屏动作
   * @param {Node} targetNode 目标节点
   * @param {number} count 震动次数
   * @param {number} time 时间
   * @return {*}
   */
  static blink(targetNode: Node, count: number = 2, time: number = 1): ActionRet<UIOpacity> {
    return new Promise((resolve) => {
      const opacity = targetNode.getComponent(UIOpacity)
      if (opacity) {
        const tw = tween(opacity)
          .set({ opacity: 255 })
          .to(0.1, { opacity: 0 })
          .delay(time)
          .to(0.1, { opacity: 255 })
          .union()
          .repeat(count)
          .call(() => {
            return resolve({ tw })
          })
          .start()
      } else {
        console.error('组件不存在')
        return resolve(null)
      }
    })
  }
  /**
   * @description: 相对移动重复
   * @param {Node} targetNode 目标节点
   * @param {Vec3} offset 移动坐标
   * @param {number} time 时间
   * @return {*}
   */
  static moveByRepeat(targetNode: Node, offset: Vec3 = v3(100, -100, 0), time: number = 1, repeatCount: number = macro.REPEAT_FOREVER): Tween<Node> {
    const endOffset = offset.clone().multiplyScalar(-1)
    const tw = tween(targetNode).by(time, { position: offset }).by(time, { position: endOffset }).union().repeat(repeatCount).start()
    return tw
  }
  /**
   * @description: 相对旋转重复运动
   * @param {Node} targetNode 目标节点
   * @param {Vec3} offsetValue 旋转度数
   * @param {number} time 时间
   * @return {*}
   */
  static rotateRepeat(offset: Vec3 = v3(0, 0, 1), time: number = 1, repeatCount: number = macro.REPEAT_FOREVER): Tween<Node> {
    const endOffset = offset.clone().multiplyScalar(-1)
    const tw = tween().by(time, { angle: endOffset }).by(time, { angle: offset }).union().repeat(repeatCount).start()
    return tw
  }
  /**
   * @description: 获取队列动作
   * @param {array} seq 动作列表
   * @return {*}
   */
  static sequenceAction(...seq: Tween<unknown>[]): Tween<unknown> {
    return tween().sequence(...seq)
  }
  /**
   * @description: 获取平行动作
   * @param {array} list 动作列表
   * @return {*}
   */
  static parallelAction(...list: Tween<unknown>[]): Tween<unknown> {
    return tween().parallel(...list)
  }
  static runAction(obj: object, tween: Tween<unknown>): Promise<Tween<unknown>> {
    return new Promise((resolve) => {
      tween
        .target(obj)
        .call(() => {
          return resolve(tween)
        })
        .start()
    })
  }
  /**
   * @description:打开窗口动作
   * @param {Prefab} pre 预制体
   * @param {Partial} scData 脚本数据
   * @param {Node} parent 父节点
   * @return {*}
   */
  openWindowAction<T>(pre: Prefab | Node, scData: Partial<T> = {}, parent?: Node): ActionRet<Node> {
    return new Promise((resolve) => {
      QuickManager.instance.createPrefab<T>(pre, scData, parent).then((tarNode) => {
        if (tarNode) {
          tarNode.setScale(v3(0.8, 0.8, 0.8))
          Action.scaleToAction(v3(1, 1, 1), 0.5, 'backOut')
            .target(tarNode)
            .call((ret) => {
              return resolve(ret)
            })
            .start()
        }
      })
    })
  }
  /**
   * @description:关闭窗口动作
   * @param {Node} tarNode 预制体
   * @param {boolean} isDes 是否销毁
   * @return {*}
   */
  closeWindowAction(tarNode: Node, isDes: boolean = true): ActionRet<Node> {
    return new Promise((resolve) => {
      Action.scaleToAction(v3(0.8, 0.8, 0.8), 0.5, 'backIn')
        .call((ret) => {
          if (isDes) {
            tarNode.destroy()
          } else {
            tarNode.active = false
          }
          return resolve(ret)
        })
        .start()
    })
  }
  /**
   * @description:按钮动作
   * @param {Node} tarNode 预制体
   * @param {boolean} isDes 是否销毁
   * @return {*}
   */
  btnAction(tarNode: Node) {
    const ac0 = tween().delay(1)
    const ac1 = Action.scaleToAction(v3(0.8, 1, 1), 0.5, 'backOut')
    const ac2 = Action.scaleToAction(v3(1, 1, 1), 1, 'bounceOut')
    Action.sequenceAction(ac0, ac1, ac2).target(tarNode).repeatForever().start()
  }
  logoAction1(logoNode: Node) {
    const ac1 = Action.scaleToAction(v3(0.8, 0.8, 1), 1)
    const ac2 = Action.scaleToAction(v3(1.2, 1.2, 1), 0.5, 'backInOut')
    const ac3 = Action.scaleToAction(v3(1, 1, 1), 0.5, 'backInOut')
    const ac4 = Action.sequenceAction(ac2, ac3).repeat(2)
    Action.sequenceAction(ac1, ac4, tween().delay(1)).target(logoNode).start()
  }
  logoAction2(logoNode: Node) {
    const ac1 = Action.scaleToAction(v3(0.7, 0.7, 1), 0.3, 'backIn')
    const ac2 = Action.scaleToAction(v3(0.9, 0.9, 1), 0.3, 'backIn')
    const ac4 = Action.scaleToAction(v3(1, 1, 1), 3, 'bounceOut')
    const ac3 = tween().delay(8)
    const seq = Action.sequenceAction(ac1, ac2).repeat(3)
    Action.sequenceAction(seq, ac4, ac3).repeatForever().target(logoNode).start()
  }
  logoAction3(logoNode: Node) {
    const ac1 = Action.rotateToAction(v3(0, 0, 15), 8, 'quadInOut')
    const ac2 = Action.rotateToAction(v3(0, 0, -15), 8, 'quadInOut')
    Action.sequenceAction(ac1, ac2).repeatForever().target(logoNode).start()
  }
}
